﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ca2simulator.shared.wcf;
using ca2simulator.shared;
using System.ServiceModel;

namespace ca2simulator.client.wcf
{

    class MySim : ISimulationCallback, IDisposable
    {
        #region Events
        public delegate void LatticeChangedHandler(object sender, Lattice data);
        public delegate void LatticeChangesHandler(object sender, CellChange[] changes);

        public event LatticeChangedHandler LatticeChanged;
        public event LatticeChangesHandler LatticeChanges;

        protected void OnLatticeChanged(Lattice data)
        {
            if(LatticeChanged!=null)
                LatticeChanged(this, data);
        }
        protected void OnLatticeChanges(CellChange[] changes)
        {
            if (changes != null)
                LatticeChanges(this, changes);
        }
        #endregion

        MySimClient _Client;



        public MySim(CA2Raw ca)
        {
            InstanceContext context = new InstanceContext(this);
            _Client = new MySimClient(context);
            _Client.Open();
            _Client.Start();
            _Client.UploadSimulation(new CAContract(ca));
            _Client.Subscribe();
        }

        #region Callback methods
        public void OnLatticeUpdate(LatticeContract updatedLattice)
        {
            if (updatedLattice != null && updatedLattice.Lattice != null)
                OnLatticeChanged(updatedLattice.Lattice);
        }
        public void OnLatticeChange(LatticeChangeContract changes)
        {
            if (changes != null)
                OnLatticeChanges(changes.Changes);
        }
        #endregion

        #region Disposable methods
        public void Dispose()
        {
            _Client.Halt();
            _Client.Unsubscribe();
            _Client.ReleaseSimulation();
            _Client.Close();
        }
        #endregion

        #region Service methods
        public LatticeContract GetLattice()
        {
            return _Client.GetLattice();
        }

        public void Run()
        {
            _Client.Run();
        }

        public void Halt()
        {
            _Client.Halt();
        }

        public LatticeContract Step(int numStep)
        {
            return _Client.Step(numStep);
        }
        #endregion

        #region Proxy partial class
        partial class MySimClient :
            DuplexClientBase<ICA2SimulationService>, ICA2SimulationService
        {
            public MySimClient(InstanceContext inputInstance) : base(inputInstance) { }

            public MySimClient(InstanceContext inputInstance, string endpointName) : base(inputInstance, endpointName) { }

            public LatticeContract GetLattice()
            {
                return Channel.GetLattice();
            }

            public bool Run()
            {
                return Channel.Run();
            }

            public bool Halt()
            {
                return Channel.Halt();
            }

            public LatticeContract Step(int numStep)
            {
                return Channel.Step(numStep);
            }

            public bool Subscribe()
            {
                return Channel.Subscribe();
            }

            public bool Unsubscribe()
            {
                return Channel.Unsubscribe();
            }

            public bool UploadSimulation(CAContract ca)
            {
                return Channel.UploadSimulation(ca);
            }

            public bool ReleaseSimulation()
            {
                return Channel.ReleaseSimulation();
            }

            public void Start()
            {
                Channel.Start();
            }
        }
        #endregion
    }
}
